'''Created on May 11, 2011

@author: mhamilton'''

import re
from functools import reduce
from operator import add
from collections import OrderedDict
try:
    from display.BoardEditor import BoardEditor
except ImportError:
    pass

from data.words import words
from data.points import points
from data.game import Game
from data.board import board



def filter_pick(list, filter):
    return [ (l, m) for l in list for m in (filter(l),) if m]

# returns true if small is a subset of big, false otherwise
def is_sub_set(big, small):
    test = big[:]
    for s in small:
        for char in s:
            if char in test:
                test[test.index(char)] = None
            else:
                return False
    return True

#input = '^%%%%%%%[loadiehw]%%%%%%%$'

def multiple_replace(text, adict):
    rx = re.compile('|'.join(map(re.escape, adict)))
    def one_xlat(match):
        return adict[match.group(0)]
    return rx.sub(one_xlat, text)

#compileStr = input

def increment_wildcards(wildcards, index):
    if index < 0:
        return None
    c = wildcards[index]
    c = chr(ord(c) + 1)
    if c == '{':
        wildcards[index] = 'a'
        return increment_wildcards(wildcards, index-1)
    wildcards[index] = c
    return wildcards

def main_search(inputBench, input, wildcards=None, best_picks = set()):
    #print(wildcards)
    inputBenchStr = ''.join(inputBench)
    #print inputBenchStr
    #print input
    curBenchStr = ''
    curBench = inputBench[:]
    for c in inputBenchStr:
        curBenchStr += c
    if wildcards:
        for c in wildcards:
            curBenchStr += c
            curBench.append(c)
    
    # reduce the input string
    simpleBenchStr = reduce(add, set(curBenchStr).intersection(curBenchStr))
    
    compileDict = OrderedDict()
    for x in xrange(14, 0, -1):
        compileDict['+'*x] = '([%s]{0,%d}?)' % (simpleBenchStr, x)
    for x in xrange(14, 0, -1):
        compileDict['-'*x] = '([%s]{0,%d}?)' % (simpleBenchStr, x)
    for x in xrange(14, 0, -1):
        compileDict['#'*x] = '([%s]{1,%d}?)' % (simpleBenchStr, x)
    for x in xrange(14, 0, -1):
        compileDict['!'*x] = '([%s]{%d}?)' % (simpleBenchStr, x)
    
    #print compileDict
    #create one regex from the above rules
    compileStr = multiple_replace(input, compileDict)  
    #print(compileStr)
    
    # compile it
    compiled = re.compile(compileStr)
    print(compileStr)
    searchRegex = compiled.search
    # run it on the word list to filter
    print("%d" % len(words))
    x = filter_pick(words, searchRegex)
    print("%d" % len(x))
    #print x
    
    # filters out all words that use more letters than are available in the bench
    x = list(filter((lambda tuple: is_sub_set(curBench, tuple[1].groups())), x))
    #print x
    
    #adds a dictionary of the matches keyed by their location
    x = [(c[0], {i:c[1].groups()[i] for i in range(len(c[1].groups()))}) for c in x]
    #print x
    
    #print(len(x))
    
    # Add to the tuple the score of the generated word
    x = [tuple + (reduce(add, [points[char] for char in tuple[0]]),) for tuple in x]
    #print x
    
    #print(random.choice(x))
        
    # sort by point value
    x = sorted(x, key=lambda point: point[2], reverse=True)
    print x
    for tup in x:
        best_picks.add((tup[0], tup[2]))
    print(best_picks)
    if wildcards is not None:
        wildcards = increment_wildcards(wildcards, len(wildcards) -1)
    return (wildcards, x)



def search_rows(game, best_picks, wildcards, cols):
    for row in cols:
        search_list = ['^']
        valid = False
        for col in row:
            if col.isalpha():
                search_list.append(col)
                valid = True
            else:
                if not valid:
                    search_list.append('+')
                else:
                    search_list.append('-')
        
        first_letter_found = False
        index = len(search_list) -1
        while index >= 0:
            col = search_list[index]
            if col.isalpha():
                first_letter_found = True
            elif first_letter_found and col == '-':
                search_list[index] = '!'
            index -= 1
        
        if valid:
            search_list.append('$')
            wildcards, x = main_search(game.bench, ''.join(search_list), wildcards=wildcards, best_picks=best_picks)
            print x

def solve(game, board):
    best_picks = set()
    wildcards = None
    search_rows(game, best_picks, wildcards, game.user)
    cols = zip(*game.user)
    search_rows(game, best_picks, wildcards, cols)
    best_pick_list = sorted(best_picks, key=lambda tup: tup[1], reverse=True )
    print (best_pick_list)

'''best_picks = set()
wildcards = []
for c in benchStr:
    if c == '*':
        wildcards.append('a')

benchStr.replace('*', '')# remove the *'s

while main_search(benchStr, wildcards): # will do the first time for sure, then attempt the increment
    wildcards = increment_wildcards(wildcards, len(wildcards) -1)
    # once done or if there are no wildcards, loop will finish

best_picks = list(best_picks)
best_picks = sorted(best_picks, key=lambda point: point[1], reverse=True)
    
print(best_picks)
for tup in best_picks:
    print("%s, %d" % (tup[0], tup[1]))'''

if __name__ == '__main__':
#    benchStr = "hmaxrsd"
    wildcards = []
    best_picks = set()
#    while wildcards is not None:
#        wildcards, x = main_search(list(benchStr), "^na--------$", wildcards, best_picks)
    be = BoardEditor(board, game=Game())
#be.mainloop()
#print(x[0][2])
